﻿using ComponentFactory.Krypton.Toolkit;
using LLMEvaluation.Framework;
using StableDiffusionTools.Forms;
using StableDiffusionTools.Interop;
using StableDiffusionTools.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LLMEvaluation.Forms
{
    public partial class RunsOverviewForm : KryptonForm
    {
        //public static Color RegularColor { get; set; } = Color.Black;
        public static Color ActionColor { get; set; } = Color.DimGray;
        public static Color QuotedColor { get; set; } = Color.Goldenrod;

        public RunsOverviewForm(List<RunEntry> runs)
        {
            InitializeComponent();

            FormatOverview(runs);

            KeyDown += (s, e) =>
            {
                if (e.KeyCode == Keys.Escape)
                {
                    DialogResult = DialogResult.Cancel;
                }
            };

            colorPreviewAction.Color = ActionColor;
            colorPreviewAction.Click += (s, e) =>
            {
                using (var colorPickerForm = new HSLColorPickerForm() { UseAlpha = false })
                {
                    if(colorPickerForm.ShowDialog(ActionColor) == DialogResult.OK)
                    {
                        colorPreviewAction.Color = ActionColor = colorPickerForm.GetHSL().ToColor();
                        FormatOverview(runs);
                    }
                }
            };

            colorPreviewQuoted.Color = QuotedColor;
            colorPreviewQuoted.Click += (s, e) =>
            {
                using (var colorPickerForm = new HSLColorPickerForm() { UseAlpha = false })
                {
                    if (colorPickerForm.ShowDialog(QuotedColor) == DialogResult.OK)
                    {
                        colorPreviewQuoted.Color = QuotedColor = colorPickerForm.GetHSL().ToColor();
                        FormatOverview(runs);
                    }
                }
            };

            StartPosition = FormStartPosition.CenterParent;
        }

        //private int GetVScrollPos()
        //{
        //    return User32.GetScrollPos(kryptonRichTextBoxOverview.Handle, User32Constants.SB_VERT);
        //}

        //private void SetVScrollPos(int pos)
        //{
        //    User32.SetScrollPos(kryptonRichTextBoxOverview.Handle, User32Constants.SB_VERT, pos, true);
        //    User32.SendMessage(kryptonRichTextBoxOverview.Handle, WindowMessage.VerticalScroll, pos << 16 | User32Constants.SB_THUMBPOSITION, 0);
        //}

        private void FormatOverview(List<RunEntry> runs)
        {
            //int scroll = GetVScrollPos();
            kryptonRichTextBoxOverview.SuspendPaint();
            kryptonRichTextBoxOverview.Clear();
            List<Tuple<int, int>> offsets = new List<Tuple<int, int>>();

            for (int i = 0; i < runs.Count; i++)
            {
                kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Regular);
                kryptonRichTextBoxOverview.AppendText("-------------------------------------------------------------------------------------------\r\n");
                kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Bold);
                kryptonRichTextBoxOverview.AppendText($"Run, {i + 1} Prompt:\r\n");
                kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Regular);
                kryptonRichTextBoxOverview.AppendText("-------------------------------------------------------------------------------------------\r\n");
                for (int j = 0; j < runs[i].PromptMessages.Count; j++)
                {
                    int startIndex = kryptonRichTextBoxOverview.Text.Length;
                    kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Underline);
                    kryptonRichTextBoxOverview.AppendText($"{runs[i].PromptMessages[j].Role}");
                    kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Regular);
                    kryptonRichTextBoxOverview.AppendText("\r\n" + runs[i].PromptMessages[j].Content + "\r\n");
                    int lenght = kryptonRichTextBoxOverview.Text.Length - startIndex;
                    offsets.Add(new Tuple<int, int>(startIndex, lenght));
                }

                for (int j = 0; j < runs[i].ModelEntries.Count; j++)
                {
                    kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Bold);
                    kryptonRichTextBoxOverview.AppendText($"\r\n{runs[i].ModelEntries[j].Name}\r\n");
                    kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Regular);
                    kryptonRichTextBoxOverview.AppendText("-------------------------------------------------------------------------------------------\r\n");
                    for (int k = 0; k < runs[i].ModelEntries[j].ResponseMessages.Count; k++)
                    {
                        int startIndex = kryptonRichTextBoxOverview.Text.Length;
                        kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Underline);
                        kryptonRichTextBoxOverview.AppendText($"{runs[i].ModelEntries[j].ResponseMessages[k].Role}");
                        kryptonRichTextBoxOverview.SelectionFont = new Font(kryptonRichTextBoxOverview.SelectionFont, FontStyle.Regular);
                        kryptonRichTextBoxOverview.AppendText("\r\n" + runs[i].ModelEntries[j].ResponseMessages[k].Content + "\r\n");
                        int lenght = kryptonRichTextBoxOverview.Text.Length - startIndex;
                        offsets.Add(new Tuple<int, int>(startIndex, lenght));
                    }
                }
            }

            foreach (var item in offsets)
            {
                string subString = kryptonRichTextBoxOverview.Text.Substring(item.Item1, item.Item2);
                var actions = Regex.Matches(subString, @"\*[^\*]*\*");
                foreach (Match action in actions)
                {
                    kryptonRichTextBoxOverview.SelectionStart = item.Item1 + action.Index;
                    kryptonRichTextBoxOverview.SelectionLength = action.Length;
                    kryptonRichTextBoxOverview.SelectionColor = ActionColor;
                }

                var quotes = Regex.Matches(subString, "\"[^\"]*\"");
                foreach (Match quote in quotes)
                {
                    kryptonRichTextBoxOverview.SelectionStart = item.Item1 + quote.Index;
                    kryptonRichTextBoxOverview.SelectionLength = quote.Length;
                    kryptonRichTextBoxOverview.SelectionColor = QuotedColor;
                }
            }

            kryptonRichTextBoxOverview.SelectionStart = 0;
            kryptonRichTextBoxOverview.SelectionLength = 0;
            //SetVScrollPos(scroll);
            kryptonRichTextBoxOverview.ResumePaint();
        }

        [Obsolete("This is not supported in this class.", true)]
        public new void Show(IWin32Window window) { }
        [Obsolete("This is not supported in this class.", true)]
        public new void Show() { }

        private void kryptonButtonCopy_Click(object sender, EventArgs e)
        {
            ClipboardUtil.SetText(kryptonRichTextBoxOverview.Text);
        }

        private void kryptonButtonSaveAs_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog
            {
                DefaultExt = "txt",
                Filter = "Text Documents|*.txt|Rich Text Format|*.rtf|All Files|*.*"
            };
            if (sfd.ShowDialog(this) == DialogResult.OK)
            {
                try
                {
                    var exists = File.Exists(sfd.FileName);
                    var fileMode = exists ? FileMode.Truncate : FileMode.CreateNew;
                    using (var stream = File.Open(sfd.FileName, fileMode, FileAccess.Write, FileShare.None))
                    using (var writer = new StreamWriter(stream))
                    {
                        if(sfd.FilterIndex == 2)
                        {
                            writer.Write(kryptonRichTextBoxOverview.Rtf);
                        }
                        else
                        {
                            writer.Write(kryptonRichTextBoxOverview.Text);
                        }
                    }
                }
                catch (Exception ex)
                {
                    KryptonMessageBox.Show(this, ExceptionUtil.FormatInnerExceptions(ex), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }
}
